package eiisan.service.user.impl;

import eiisan.dao.param.user.DoLogin;
import eiisan.dao.result.user.PermissionInfo;
import eiisan.dao.result.user.UserDetail;
import eiisan.service.user.AuthorityService;
import eiisan.service.user.LoginService;
import eiisan.config.security.util.JwtTokenUtil;
import eiisan.util.model.response.Result;
import eiisan.util.spring.MVCUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.stream.Collectors;

/**
 * LoginServiceImpl
 * @author gragonfly
 * @date 2019/7/6
 **/
@Slf4j
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class LoginServiceImpl implements LoginService{
    /**
     * spring security验证管理器
     */
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private SecurityContextLogoutHandler logoutHandler;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthorityService authorityService;

    @Override
    public Result login(@Valid @NotNull DoLogin param) {
        try {
            Result<UserDetail> result = authorityService.getUserDetailByUsername(param.getUsername());
            if (Result.isNotSuccess(result)) {
                return result;
            }
            UserDetail userDetail = result.getData();
            if (!passwordEncoder.matches(param.getPassword(), userDetail.getPassword())) {
                return Result.fail("用户名或密码错误!");
            }

            List<String> authorities = userDetail.getPermissions().stream().map(PermissionInfo::getName).collect(
                    Collectors.toList());
            //realToken
            String token = JwtTokenUtil.generate(param.getUsername(), authorities);


//            SecurityContextHolder.getContext().setAuthentication(authenticationManager.authenticate(
//                    new UsernamePasswordAuthenticationToken(param.getUsername(), param.getPassword())));
            return Result.success(token);
        } catch (Exception e) {
            log.error("[login]", e);
            return Result.errorServe();
        }
    }

    @Override
    public Result logout() {
        HttpServletRequest request = MVCUtil.request();
        String token = JwtTokenUtil.getRealToken(request);
        logoutHandler.logout(request, MVCUtil.response(), SecurityContextHolder.getContext().getAuthentication());
        return Result.success();
    }

}
